import { Graph, FunctionExt, Shape } from "@antv/x6";
import { Stencil } from "@antv/x6-plugin-stencil";
import { Selection } from "@antv/x6-plugin-selection";
import { Keyboard } from "@antv/x6-plugin-keyboard";
import { Scroller } from "@antv/x6-plugin-scroller";
import { Snapline } from "@antv/x6-plugin-snapline";
import { History } from "@antv/x6-plugin-history";
import { Clipboard } from "@antv/x6-plugin-clipboard";
import { Export } from "@antv/x6-plugin-export";
import { Transform } from "@antv/x6-plugin-transform";

// 导入本地SVG文件
import clientSvg from "@/assets/flow-icons/client.svg";
import httpSvg from "@/assets/flow-icons/http.svg";
import apiSvg from "@/assets/flow-icons/api.svg";
import sqlSvg from "@/assets/flow-icons/sql.svg";
import cloudSvg from "@/assets/flow-icons/cloud.svg";
import mqSvg from "@/assets/flow-icons/mq.svg";

import "./shape";
import graphData from "./data";
import { globalGridAttr } from "../models/global";

export default class FlowGraph {
  public static graph: Graph;
  private static stencil: Stencil;

  public static init() {
    this.createGraph();
    this.usePlugins();
    this.initStencil();
    this.initShape();
    this.initGraphShape();
    this.initEvent();
    return this.graph;
  }

  private static createGraph() {
    this.graph = new Graph({
      container: document.getElementById("container")!,
      grid: true,
      mousewheel: {
        enabled: true,
        zoomAtMousePosition: true,
        modifiers: "ctrl",
        minScale: 0.5,
        maxScale: 3
      },
      connecting: {
        router: "manhattan",
        connector: {
          name: "rounded",
          args: {
            radius: 8
          }
        },
        anchor: "center",
        connectionPoint: "anchor",
        allowBlank: false,
        snap: {
          radius: 20
        },
        createEdge() {
          return new Shape.Edge({
            attrs: {
              line: {
                stroke: "#5F95FF",
                strokeWidth: 1,
                targetMarker: {
                  name: "block",
                  width: 12,
                  height: 8
                }
              }
            },
            zIndex: 0
          });
        },
        validateConnection({ targetMagnet }) {
          return !!targetMagnet;
        }
      },
      highlighting: {
        magnetAdsorbed: {
          name: "stroke",
          args: {
            attrs: {
              fill: "#5F95FF",
              stroke: "#5F95FF"
            }
          }
        }
      },
      // 添加 embedding 配置以支持节点拖拽到组中
      embedding: {
        enabled: true,
        findParent({ node }) {
          const bbox = node.getBBox();
          return this.getNodes().filter(targetNode => {
            // 只有 data.parent 为 true 的节点才是父节点
            const data = targetNode.getData<any>();
            if (data && data.parent) {
              const targetBBox = targetNode.getBBox();
              return bbox.isIntersectWithRect(targetBBox);
            }
            return false;
          });
        }
      }
    });
  }

  // #region 使用插件
  private static usePlugins() {
    this.graph
      .use(
        new Transform({
          resizing: true,
          rotating: true
        })
      )
      .use(
        new Selection({
          multiple: true,
          rubberband: true,
          movable: true,
          showNodeSelectionBox: true
        })
      )
      .use(new Snapline())
      .use(new Keyboard())
      .use(new Clipboard())
      .use(new Export())
      .use(new Scroller())
      .use(new History());
  }

  // #region 初始化 stencil
  private static initStencil() {
    this.stencil = new Stencil({
      title: "流程图",
      target: this.graph,
      stencilGraphWidth: 200,
      stencilGraphHeight: 180,
      collapsable: true,
      groups: [
        {
          title: "基础流程图",
          name: "group1"
        },
        {
          title: "系统设计图",
          name: "group2",
          graphHeight: 250,
          layoutOptions: {
            rowHeight: 70
          }
        }
      ],
      layoutOptions: {
        columns: 2,
        columnWidth: 80,
        rowHeight: 55
      }
    });
    document.getElementById("stencil")!.appendChild(this.stencil.container);
  }
  // #region 初始化节点
  private static initShape() {
    const { graph } = this;
    const r1 = graph.createNode({
      shape: "custom-rect",
      label: "开始",
      attrs: {
        body: {
          rx: 20,
          ry: 26
        }
      }
    });
    const r2 = graph.createNode({
      shape: "custom-rect",
      label: "过程"
    });
    const r3 = graph.createNode({
      shape: "custom-rect",
      attrs: {
        body: {
          rx: 6,
          ry: 6
        }
      },
      label: "可选过程"
    });
    const r4 = graph.createNode({
      shape: "custom-polygon",
      attrs: {
        body: {
          refPoints: "0,10 10,0 20,10 10,20"
        }
      },
      label: "决策"
    });
    const r5 = graph.createNode({
      shape: "custom-polygon",
      attrs: {
        body: {
          refPoints: "10,0 40,0 30,20 0,20"
        }
      },
      label: "数据"
    });
    const r6 = graph.createNode({
      shape: "custom-circle",
      label: "连接"
    });
    this.stencil.load([r1, r2, r3, r4, r5, r6], "group1");

    const imageShapes = [
      {
        label: "Client",
        image: clientSvg
      },
      {
        label: "Http",
        image: httpSvg
      },
      {
        label: "Api",
        image: apiSvg
      },
      {
        label: "Sql",
        image: sqlSvg
      },
      {
        label: "Clound",
        image: cloudSvg
      },
      {
        label: "Mq",
        image: mqSvg
      }
    ];
    const imageNodes = imageShapes.map(item =>
      graph.createNode({
        shape: "custom-image",
        label: item.label,
        attrs: {
          image: {
            "xlink:href": item.image
          }
        },
        // 为stencil中的节点设置较小的默认大小
        size: { width: 52, height: 52 }
      })
    );
    this.stencil.load(imageNodes, "group2");
    // #endregion
  }

  // #region 初始画布图形
  private static initGraphShape() {
    this.graph.fromJSON(graphData as any);
  }

  private static showPorts(ports: NodeListOf<SVGAElement>, show: boolean) {
    for (let i = 0, len = ports.length; i < len; i = i + 1) {
      ports[i].style.visibility = show ? "visible" : "hidden";
    }
  }

  private static initEvent() {
    const { graph } = this;
    const container = document.getElementById("container")!;

    // 监听节点文本变化事件，同步更新全局状态
    graph.on("node:change:attrs", ({ cell }) => {
      // 当节点属性变化时，更新全局状态中的文本值
      if (cell.isNode()) {
        const text = cell.attr("text/text");
        if (text !== undefined) {
          // 更新全局状态中的 nodeText 值
          globalGridAttr.nodeText = text as string;
        }
      }
    });

    graph.on(
      "node:mouseenter",
      FunctionExt.debounce(() => {
        const ports = container.querySelectorAll(".x6-port-body") as NodeListOf<SVGAElement>;
        this.showPorts(ports, true);
      }),
      500
    );
    graph.on("node:mouseleave", () => {
      const ports = container.querySelectorAll(".x6-port-body") as NodeListOf<SVGAElement>;
      this.showPorts(ports, false);
    });

    graph.on("node:collapse", ({ node, e }: any) => {
      e.stopPropagation();
      node.toggleCollapse();
      const collapsed = node.isCollapsed();
      const cells = node.getDescendants();
      cells.forEach((n: any) => {
        if (collapsed) {
          n.hide();
        } else {
          n.show();
        }
      });
    });
    // backspace
    graph.bindKey("delete", () => {
      const cells = (graph.getPlugin("selection") as Selection).getSelectedCells();
      if (cells.length) {
        graph.removeCells(cells);
      }
    });
  }
}

export { FlowGraph };
